<template>
  <div>
    <el-button 
      size="small" 
      type="primary" 
      @click="genBoxGeometry"
    >生成立方体</el-button
    >
    <el-button 
      size="small" 
      type="primary" 
      @click="genLongBoxGeometry"
    >生成长方体</el-button
    >
    <el-button 
      size="small" 
      type="primary" 
      @click="genCylinderGeometry"
    >生成圆柱</el-button
    >
    <el-button 
      size="small" 
      type="primary" 
      @click="genLongCylinderGeometry"
    >生成椭圆柱</el-button
    >
    <el-button 
      size="small" 
      type="primary" 
      @click="outputPdf"
    >导出pdf</el-button
    >
    <!-- <el-button size="small" type="primary" @click="calGirth"
      >计算长度</el-button
    > -->
    <div>鼠标左键拖动可以转变视角；鼠标右键拖动可以缩放以及移动</div>
    <div>预计总长度：{{ calGirth }}(每次更新参数后需要重新计算长度)</div>
    <div id="content"></div>
  </div>
</template>

<script>
import {
  Scene,
  PerspectiveCamera,
  WebGLRenderer,
  Mesh,
  Cache,
  Color
  // eslint-disable-next-line import/no-duplicates
} from 'three';
// eslint-disable-next-line import/no-duplicates
import * as THREE from 'three';
import dat from 'dat.gui';
import JsPdf from 'jspdf';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

export default {
  name: 'Editor',
  data() {
    return {
      scene: null,
      camera: null,
      renderer: null,
      mesh: null,
      geometry: null,
      color: '#ffffff',
      //   宽度
      width: '10',
      //   高度
      height: '10',
      //   深度
      depth: '10',
      //   灯光
      envLight: null,
      pointLight: null,
      //   交互插件
      orbitControls: null,
      //  总长度
      // girth: 0,
      //   原先宽度、高度、深度
      pWidth: null,
      pHeight: null,
      pDepth: null,
      // 当前宽度、高度、深度
      cWidth: null,
      cHeight: null,
      cDepth: null,
      //   行数
      lines: '1',
      //   dat.gui
      gui: null,
      // 是否拉长
      isLong: false,
      // 基础长度 圆半径&正方形边长
      baseLength: 10,
      // 当前几何体类型
      currentGeoType: 'circle'
    };
  },
  computed: {
    // 计算长度
    calGirth() {
      let girth = 0;
      if (this.currentGeoType === 'circle') {
        let x =
          this.lines % 2 === 0
            ? this.width / 2 / (this.lines + 1)
            : this.width / (this.lines + 1);
        let y =
          (this.height / 2) *
          Math.sqrt(1 - Math.pow(x, 2) / Math.pow(this.width / 2, 2));
        girth = y * this.lines * 2 + 2 * x;
      } else if (this.currentGeoType === 'box') {
        girth =
          this.lines * this.width +
          ((this.lines - 1) * this.height) / (this.lines + 1);
      } else {
        girth = 0;
      }
      return girth.toFixed(2);
    }
  },
  async mounted() {
    // 缓存设置
    Cache.enabled = true;
    // 新增场景
    this.initScene();
    this.initLight();
    this.initCamera();
    this.initRenderer();
    this.initGui();
    this.initOrbitControls();
    this.genCylinderGeometry();
    // this.genMesh()

    // 添加canvas到dom上
    document.getElementById('content').appendChild(this.renderer.domElement);
    // 监听resize事件
    window.addEventListener('resize', () => this.onWindowResize());
    this.render();
  },
  methods: {
    // 手动更新gui
    updateGUI() {
      for (let i in this.gui.__controllers) {
        this.gui.__controllers[i].updateDisplay();
      }
    },
    // 计算长度、高度、深度
    cal3Length() {
      if (this.isLong) {
        this.width = this.baseLength * 1.5;
      } else {
        this.width = this.baseLength;
      }
      this.height = this.baseLength;
      this.depth = this.baseLength;
      this.updateGUI();
    },

    // 初始化灯光
    initLight() {
      this.envLight = new THREE.AmbientLight(0x404040, 2);
      this.pointLight = new THREE.PointLight(0xffffff, 0.5);
      this.pointLight.position.set(-40, 40, 40);
      this.pointLight2 = new THREE.PointLight(0xffffff, 0.25);
      this.pointLight2.position.set(40, -40, -40);
      this.scene.add(this.envLight);
      this.scene.add(this.pointLight);
      this.scene.add(this.pointLight2);
    },
    // 导出pdf
    outputPdf() {
      const dom = this.renderer.domElement;
      let pdf = new JsPdf('', 'pt');
      pdf.addImage(dom.toDataURL(), 'png', 0, 20, 600, 400);
      pdf.save('demo.pdf');
      console.log(dom.toDataURL(), dom.width);
    },
    // 初始化舞台
    initScene(mesh) {
      this.scene = new Scene();
      this.scene.background = new Color(0x444444);
      // this.scene.fog = new Fog(0x000000, 250, 1400)
    },
    // 实例化相机
    initCamera() {
      this.camera = new PerspectiveCamera(75, 600 / 400, 0.1, 1000);
      this.camera.position.set(20, 20, 50);
    },
    // 实例化渲染者
    initRenderer() {
      this.renderer = new WebGLRenderer({
        antialias: true,
        preserveDrawingBuffer: true
      });
      this.renderer.setSize(600, 400);
    },
    // 初始化 dat.gui
    initGui() {
      this.gui = new dat.GUI();
      this.gui.domElement.className += ' dat-style-reset';
      this.gui.addColor(this, 'color').onFinishChange(value => {
        this.updateScene();
      });
      this.gui.add(this, 'width');
      this.gui.add(this, 'height');
      this.gui.add(this, 'depth');
      this.gui.add(this, 'lines');
    },
    // 初始化交互插件
    initOrbitControls() {
      this.orbitControls = new OrbitControls(
        this.camera,
        this.renderer.domElement
      );
    },
    // 生成mesh
    genMesh() {
      const fc = new Color(this.color);
      // 颜色 基础材质 无光线
      // const material = new MeshBasicMaterial({ color: fc })
      // const meshBasicMaterial = new MeshBasicMaterial({ map: boxTexture })
      const material = new THREE.MeshPhongMaterial({
        color: fc,
        flatShading: true
      });
      //  const material = new MeshDepthMaterial({ map: boxTexture })
      this.mesh = new Mesh(this.geometry, material);
      if (this.isLong) {
        this.mesh.scale.x = 1.5;
      }
      this.mesh.name = 'geo';
    },
    updateScene() {
      this.scene.remove(this.mesh);
      this.genMesh();
      this.scene.add(this.mesh);
    },
    // 生成圆柱
    genCylinderGeometry() {
      this.geometry = new THREE.CylinderGeometry(
        this.baseLength,
        this.baseLength,
        this.height,
        80
      );
      this.isLong = false;
      this.cal3Length();
      this.updateScene();
      this.currentGeoType = 'circle';
    },
    // 生成椭圆柱
    genLongCylinderGeometry() {
      this.geometry = new THREE.CylinderGeometry(
        this.baseLength,
        this.baseLength,
        this.height,
        80
      );
      this.isLong = true;
      this.cal3Length();
      this.updateScene();
      this.currentGeoType = 'circle';
    },
    // 生成立方体
    genBoxGeometry() {
      this.geometry = new THREE.BoxGeometry(this.baseLength * 2, 20, 20);
      this.isLong = false;
      this.cal3Length();
      this.updateScene();
      this.currentGeoType = 'box';
    },
    // 生成长方体
    genLongBoxGeometry() {
      this.geometry = new THREE.BoxGeometry(this.baseLength * 2, 20, 20);
      this.isLong = true;
      this.cal3Length();
      this.updateScene();
      this.currentGeoType = 'box';
    },

    onWindowResize() {
      // this.renderer.setSize(400, window.innerHeight / 2)
    },
    render() {
      window.requestAnimationFrame(() => this.render());
      this.mesh.scale.x = this.width / this.baseLength;
      this.mesh.scale.z = this.height / this.baseLength;
      this.mesh.scale.y = this.depth / this.baseLength;
      //   text.scale.x = this.long
      //   text.scale.y = this.wide
      //   text.scale.z = this.height
      // console.log(text.scale)
      this.renderer.render(this.scene, this.camera);
    }
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
.dat-style-reset {
  right: initial;
  left: 10px;
  top: 90px;
  position: absolute;
}
#content {
  margin-left: 300px;
}
</style>
